<template>
    <div :class="['container', hasType ? 'has-type' : '']">
        <div class="chart-search">
            <el-select 
                v-model="particleSize" 
                placeholder="请选择" 
                size="small"
                @change="handleChangeSize"
                class="particleSize"
                v-if="showParticleSize">
                <el-option
                    v-for="item in particleSizeArr"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value">
                </el-option>
            </el-select>
        </div>
        <div class="chart-content">
            <div :id="container" class="chart-views"></div>
        </div>
    </div>
</template>
<script>
import { dateFormatter, formatterNum, formatterNumber } from '@/common/js/util.js'
import Highcharts from 'highcharts';
export default {
    props: {
        dataArr: {
            type: Object,
            default: {}
        }, 
        showParticleSize: {
            type: Boolean,
            default: false
        }, 
        container: {
            type: String,
            default: 'c1'
        }, 
        hasType: {
            type: Boolean,
            default: true
        }, 
        upComponent: {
            type: Boolean,
            default: false
        }, 
        _particleSize: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            particleSizeArr: [
                {label: '日粒度', value: 'day'},
                {label: '周粒度', value: 'week'},
                {label: '月粒度', value: 'month'}
            ],
            charts: null,
            particleSize: 'day',       // 粒度
        }
    },
    methods: {
        // 粒度计算
        handleChangeSize() {
            // 传递给其他兄弟组件
            if(this.upComponent) {
                this.$emit('upParticleSize', this.particleSize)
            }
            // this.updateChart(this.dataArr.series); // 仅更新数据
            this.chartInit(this.dataArr); // 重新初始化
        },
        formatData(data = []) {
            let particleSize = this.particleSize,
                keys = 0,
                _data = [];
            for(let [_key, value] of data.entries()) {
                let _value = this.formatStringToTime(value[0]), date_value = _value;
                if(!_data[keys]) {
                    _data[keys] = [[], 0]; // [] - 存储日期, 0 // 总值 
                }
                //_data[keys][1] = Math.ceil(value[1] + _data[keys][1]); // 计算总值
                _data[keys][1] = value[1] + _data[keys][1]; // 计算总值
                if(particleSize == 'week') date_value = dateFormatter('YYYYMMDD', _value)
                if(_data[keys][0][0]) {
                    _data[keys][0][1] = date_value
                } else {
                    _data[keys][0].push(date_value)
                }
                if(particleSize == 'day' || 
                   particleSize == 'week' && new Date(_value).getDay() == 0 || 
                   particleSize == 'month' && new Date(_value).getMonth() != 
                   new Date(_value + 24 * 3600 * 1000).getMonth()) 
                {
                    keys++;
                }
            }
            _data = _data.map(item => {
                if(particleSize == 'day') {
                    //item[0] = this.formatStringToTime(item[0][0]) // 转时间戳
                    item[0] = item[0][0]
                } else if(particleSize == 'week') {
                    item[0] = item[0].join("-") // 转字符串
                } else if(particleSize == 'month') {
                    item[0] = dateFormatter('YYYYMM', item[0][0]) // 转月份字符串
                }
                return item;
            })
            return _data;
        },
        formatStringToTime(str) {
            if(typeof str !== 'string') return str;
            return new Date(str.replace(/^(\d{4})(\d{2})(\d{2})$/, "$1-$2-$3")).getTime()
        },
        chartInit(dataArr = null) {
            const that = this;
            const _dataArr = dataArr
            dataArr = JSON.parse(JSON.stringify(dataArr));
            dataArr.series = dataArr.series.map(item => {
                // 针对series每个图形元素单独设置填充色
                item.fillColor = {
                    linearGradient: { x1: 0, x2: 0, y1: 0, y2: 0.9 }, // 线性渐变
		    	    stops: [
		    	        [0, Highcharts.color(item.color).setOpacity(0.3).get('rgba')],
		    	        [1, Highcharts.color(item.color).setOpacity(0).get('rgba')]
		    	    ]
                }
                // 根据粒度格式数组
                item.data = this.formatData(item.data);
                return item;
            })
            
            // 设置千分分隔符为 ','
            Highcharts.setOptions({
                lang: { thousandsSep: ',' } 
            })
            this.charts = Highcharts.chart(this.container, {
                chart: { 
                    type: 'areaspline', // 类型：普通面积图(直线) area, 面积曲线图 - areaspline,
                }, 
	            title: Object.assign({
                    text: null,
                    align: 'center',
                    useHTML: true,
                    margin: 35,
                    y: 5,
                    style: { 
                        "color": dataArr.series[0].color, 
                        "fontSize": "15px",
                        "fontWeight": 'bold',
                        "display": 'block',
                        "backgroundColor": Highcharts.color(dataArr.series[0].color).setOpacity(0.1).get('rgba'),
                    }
                }, dataArr.title || {}),
                credits: { enabled: false },  // 去版权水印
                exporting: { enabled: false }, // 隐藏导出
                yAxis: Object.assign({
	            	title: false,
                    allowDecimals: false, // 禁止出现小数
                    minRange: 19, // 最小范围
                    min: 0, // 最小刻度值
	            }, dataArr.yAxis || {}),
		        xAxis: {
                    type: that.particleSize == 'day' ? 'datetime' : 'category',
                    dateTimeLabelFormats: {
                        day: '%Y%m%d' // 时间格式化
                    },
                    labels: {
                        y: 22,
                        formatter: function() {
                            if(this.axis.options.type == 'datetime') {
                                return dateFormatter(dataArr.labelFormat || "YYYYMMDD", this.value) // 标签格式化，针对缩小时日期变为英文格式
                            }
                            return this.value
                        }
                    },
                    tickWidth: 1,
                    tickmarkPlacement: 'on',
                    tickLength: 5, // 刻度线长度
	            	crosshair: {
	            		dashStyle: 'Solid', // 十指辅助线
                        width: 1,
                        color: '#cccccc'
	            	},
                    tickPositioner: function (min, max) {
                        const interval = this.options.type == 'datetime' ? 24 * 3600 * 1000 : 1;
			        	const diff = (this.dataMax - this.dataMin) / (interval), width = this.width;
                        const tickAmount = dataArr.labelFormat == 'MM-DD' ? 15 : 10
                        let step = Math.floor(width * tickAmount / 1080); // 根据宽度自动调整 步阶(width = 1080px 可以放 10 个刻度)
                        if(step > diff) {
                            step = diff
                        }
                        var positions = [],
			        		tick = Math.floor(this.dataMin),
			        		increment = Math.ceil(diff / step) * interval; // 增量
			        	for (tick; tick - increment < this.dataMax; tick += increment) {
                            // if(tick < this.dataMax && (tick + increment) > this.dataMax) {
                            if(tick + increment > this.dataMax) {
                                tick = this.dataMax;
                            }
			        		positions.push(tick);
			        	}
                        if(positions.length < 1) positions = [0] // 当min = max = 0的情况下，需默认给出一个初始值
			        	return positions;
			        },
		        },
                tooltip: Object.assign({
                    shared: true, // 数据共享
                    // shape: 'callout', // 提示框形状, 默认 callout
                    borderRadius: 6,  // 当前highcharts版本 提示框为 square 值时，圆角值无效 
                    borderWidth: 0,
                    backgroundColor: 'rgba(255, 255, 255, 0.9)',
                    useHTML: true,
                    formatter: function() {
                        // const value = this.points[0].point.series.xAxis.options.type == 'datetime' ? dateFormatter("YYYYMMDD", this.x) : this.points[0].key;
                        // const valueSuffix = dataArr.tooltip ? dataArr.tooltip.valueSuffix : '';
                        // const _y = formatterNumber(this.y, 100000, 2, true)
                        // return `<small style="margin-bottom:5px;display:block">${value}</small><span style="color:${this.points[0].color};font-size:14px">●</span> ${this.points[0].series.name}: ${_y}${valueSuffix}<br/>`

                        let html = null;
                        let valueSuffix = dataArr.tooltip ? dataArr.tooltip.valueSuffix : '';
                        this.points.forEach(point => {
                            let value = point.series.xAxis.options.type == 'datetime' ? dateFormatter("YYYYMMDD", point.x) : point.key;
                            if (point.series.tooltipOptions.valueSuffix) {
                                valueSuffix = point.series.tooltipOptions.valueSuffix
                            }
                            const _y = formatterNumber(point.y, 100000, 2, true)
                            if(!html) html = `<small style="margin-bottom:5px;display:block">${value}</small><span style="color:${point.color};font-size:14px">●</span> ${point.series.name}: ${formatterNum(point.y)}${point.series.tooltipOptions.valueSuffix}<br/>`
                            else html = html + `<span style="color:${point.color};font-size:14px">●</span> ${point.series.name}: ${_y}${valueSuffix}<br/>` 
                        })
                        return html
                    },
                    padding: 12
                }, dataArr.tooltip || {}),
                legend: {
                    enabled: false, // 隐藏图例
                    symbolHeight: 10
                },
                /* 下面的是通用配置 */
	            plotOptions: Object.assign({
	            	areaspline: {
	            		dashStyle: 'Solid',
	            	},
                    series: {
	            		fillOpacity: 0.2,
                        lineWidth: 2,
                        marker: {
                            radius: 4,
                            lineWidth: 1,
                            lineColor: '#ffffff',
                            enabled: dataArr.series[0].data.length < 31 ? true : false, // 线上标记圆点, 当数据长度大于 31 则不显示标记点，否则太紧凑
                            states: {
                                hover: { // 标记(marker)悬停状态
                                    enabled: true,
                                    radiusPlus: 0,
                                    lineWidthPlus: 1
                                }
                            }
                        },
                        states: { // 线、面、柱状态
                            hover: { // 区域悬停状态
                                lineWidth: 2,
                                enabled: true
                            }
                        }
                    }
	            }, dataArr.plotOptions || {}),
		        series: dataArr.series
            })
        },
        updateChart(val) {
            const type = this.particleSize == 'day' ? 'datetime' : 'category';
            this.charts.xAxis[0].update({
                type
            })
            val = JSON.parse(JSON.stringify(val))
            for(let [index, item] of Object.entries(val)) {
                item.data = this.formatData(item.data);
                this.charts.series[index].update({
                    data: item.data
                })
            }
        }
    },
    watch: {
        'dataArr.series': function(val, oldVal) {
            if(this.particleSize != 'day') this.particleSize = 'day'; // 重置粒度
            // if(!this.charts) {
                this.chartInit(this.dataArr); // 重新初始化
            // } else {
            //    this.updateChart(val); // 仅更新类型及数据
            // }
        },
        '_particleSize': function(val, oldVal) {
            if(val) {
                this.particleSize = val;
                this.handleChangeSize();
            }
        }
    }
}
</script>
<style lang="scss" scoped>
    .container, .chart-views {
        width: 100%;
        height: 100%;
    }
    .chart-search {
        position: relative;
        height: 20px;
        /deep/.el-select {
            width: 120px;
            &.particleSize {
                position: absolute;
                right: 0;
                z-index: 100;
            }
        }
    }
    .chart-content {
        box-sizing: border-box;
        width: 100%;
        height: calc(100% - 22px);
        padding: 0 0 20px;
    }
    .has-type {
        .chart-search { height: 62px;}
        .chart-content { height: calc(100% - 62px); }
    }
    /deep/.highcharts-halo.highcharts-color-undefined{
        fill: transparent; // 清除标记点 阴影背景
    }
</style>